Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Xml.Linq
Imports System.Reflection

Public Module TimeZoneLocationService
    ' Cached collection of mappings between Olson time zone names and Windows time zone names
    Private mappings As New Dictionary(Of String, OlsonTimeZoneMapping)()

    Sub New()
        CacheMappings()
    End Sub

    ' http://www.earthtools.org/webservices.htm
    ' http://www.geonames.org
    Public Function GetBaseUtcOffsetByCoordinates(ByVal latitude As Double, ByVal longitude As Double) As System.Nullable(Of Double)
        ' http://www.geonames.org/export/web-services.html

        Dim doc As XDocument = XDocument.Load("http://ws.geonames.org/timezone?lat=" + latitude + "&lng=" + longitude + "&style=full")
        Dim tzInfo As XElement = (From node In doc.Elements("geonames").Elements("timezone") _
         Select node).FirstOrDefault()

        If tzInfo Is Nothing Then
            Return Nothing
        End If
        Dim gmtOffset As Double = Convert.ToDouble(tzInfo.Element("gmtOffset").Value)

        '<timezone>
        '                <countryCode>ES</countryCode>
        '                <countryName>Spain</countryName>
        '                <lat>39.5</lat>
        '                <lng>-5.97</lng>
        '                <timezoneId>Europe/Madrid</timezoneId>
        '                <dstOffset>2.0</dstOffset>
        '                <gmtOffset>1.0</gmtOffset>
        '                <rawOffset>1.0</rawOffset>
        '                <time>2009-11-02 01:31</time>
        '            </timezone>

        Return gmtOffset
    End Function

    Public Function GetTimeZoneInfoByCoordinates(ByVal latitude As Double, ByVal longitude As Double) As TimeZoneInfo
        ' http://www.geonames.org/export/web-services.html

        Dim doc As XDocument = XDocument.Load("http://ws.geonames.org/timezone?lat=" + latitude + "&lng=" + longitude + "&style=full")
        Dim tzInfo As XElement = (From node In doc.Elements("geonames").Elements("timezone") _
         Select node).FirstOrDefault()

        If tzInfo Is Nothing Then
            Return Nothing
        End If

        Return FindByTZID(tzInfo.Element("timezoneId").Value)
    End Function

    Public Function FindByTZID(ByVal tzid As String) As TimeZoneInfo
        Dim tzm As OlsonTimeZoneMapping = Nothing
        mappings.TryGetValue(tzid, tzm)
        If Not tzm Is Nothing Then
            Return TimeZoneInfo.FindSystemTimeZoneById(tzm.WindowsName)
        Else
            Return Nothing
        End If
    End Function

    Private Sub CacheMappings()
        Dim a As Assembly = Assembly.GetExecutingAssembly()

        Using sr As New System.IO.StreamReader(a.GetManifestResourceStream("MefTZAddin.TZDB.csv"))
            Dim row As String = String.Empty
            Dim col As String()
            Dim tzm As OlsonTimeZoneMapping
            While (row = sr.ReadLine()) <> Nothing
                col = row.Split(","c)
                tzm = New OlsonTimeZoneMapping()
                If Not mappings.ContainsKey(tzm.OlsonName) Then
                    mappings.Add(tzm.OlsonName, tzm)
                End If

                If Not mappings.ContainsKey(tzm.WindowsName) Then
                    mappings.Add(tzm.WindowsName, tzm)
                End If
            End While
        End Using
    End Sub
End Module

Class OlsonTimeZoneMapping
    Public OlsonName As String
    Public WindowsName As String
End Class
